﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Aop.Api.Domain;
using DocumentFormat.OpenXml.Spreadsheet;
using Elastic.Clients.Elasticsearch.IndexLifecycleManagement;
using Furion.JsonSerialization;
using Newtonsoft.Json;
using SL.NET.Core.Service;
using StackExchange.Profiling.Internal;
using StackExchange.Redis;
using System.Drawing;
using WCS.Application.Entity.Warehous;
using WCS.Application.Service.Inventory.DTO;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace WCS.Application.Service.Rcs;
/// <summary>
/// AGV调度服务
/// </summary>
/// 
[ApiDescriptionSettings(groups: ApplicationConst.GroupName, Order = 14)]
[AllowAnonymous]


public class DispatchService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<AgvactionsEntity> _agvactionsRepo;
    private readonly RcsService _rcsService;
    private readonly SemaphoreSlim _taskIdLock = new SemaphoreSlim(1, 1); // 用于线程同步
    private int currentActionSort = 0; // 动作组排序值，从0开始
    private int AgainSort = 0; //重新下动作任务时的排序字段
    private readonly UserManager _usermanager;
    //redis
    private readonly SysCacheService _sysCacheService;

    public DispatchService(
        SqlSugarRepository<AgvactionsEntity> agvactionsRepo,
        RcsService rcsService, UserManager usermanager, SysCacheService sysCacheService)
    {
        _agvactionsRepo = agvactionsRepo;
        _rcsService = rcsService;
        _usermanager = usermanager;
        _sysCacheService = sysCacheService;
    }

    #region 核心流程入口（适配新请求类）
    #region 核心流程入口
    [ApiDescriptionSettings(Name = "DispatchPlan"), HttpPost]
    [DisplayName("生成AGV动作计划")]
    public async Task<ServiceResult> ProcessRequest(BaseRequest request)
    {
        try
        {
            var actionType = request.Agvtype?.Trim().ToLower();
            if (!new[] { "inbound", "outbound", "recharge", "dispatch" }.Contains(actionType))
            {
                return ServiceResult.Failed("Agvtype必须为'inbound'或'outbound'或'recharge'，'Dispatch'");
            }

            var result = actionType switch
            {
                "inbound" => await ProcessInboundRequest(request),
                "outbound" => await ProcessOutboundRequest(request),
                "recharge" => await ProcessRechargeRequest(request),
                "dispatch" => await ProcessDispatchRequest(request),
                _ => ServiceResult.Failed("不支持的业务类型")
            };
            SerilogHelper.WriteLog("DispatchServiceAndProcessRequest", "select", JsonHelper.ObjectToJson(result));
            return result;
        }
        catch (CustomFriendlyException ex)
        {
            return ServiceResult.Failed(ex.Message);
        }
    }
    //入库
    private async Task<ServiceResult> ProcessInboundRequest(BaseRequest request)
    {
        if (request is not InboundRequest inboundRequest)
        {
            inboundRequest = new InboundRequest
            {
                TaskId = request.TaskId,
                AgvCode = request.AgvCode,
                AgvCurrentPos = request.AgvCurrentPos,
                Startcoord = request.Startcoord,
                TargetFloor = request.TargetFloor,
                TargetPointCoord = request.TargetPointCoord,
                StoragePosCoord = request.StoragePosCoord,
                Palletcode = request.Palletcode,
                Speed = request.Speed,
                Agvtype = request.Agvtype
            };
        }

        return await CreateInboundPlan(inboundRequest);
    }
    //出库

    private async Task<ServiceResult> ProcessOutboundRequest(BaseRequest request)
    {
        if (request is not OutboundRequest outboundRequest)
        {
            outboundRequest = new OutboundRequest
            {
                TaskId = request.TaskId,
                AgvCode = request.AgvCode,
                AgvCurrentPos = request.AgvCurrentPos,
                Startcoord = request.Startcoord, // 提升机标识（如：12）
                TargetFloor = request.TargetFloor,
                SourceStoragePosCoord = request.StoragePosCoord, // 源库位坐标
                ExitPos = request.Startcoord, // 提升机标识
                Palletcode = request.Palletcode,
                Speed = request.Speed,
                Agvtype = request.Agvtype,
                TargetPointCoord = request.TargetPointCoord // 目标可行走坐标
            };
        }

        return await CreateOutboundPlan(outboundRequest);
    }
    //调货
    private async Task<ServiceResult> ProcessDispatchRequest(BaseRequest request)
    {
        if (request is not DispatchRequest dispatchRequest)
        {
            dispatchRequest = new DispatchRequest
            {
                TaskId = request.TaskId,
                AgvCode = request.AgvCode,
                AgvCurrentPos = request.AgvCurrentPos,
                Startcoord = "12",//提升机位置
                DispatchCoord = request.DispatchCoord, //调货货物点位
                DispatchPosCoord = request.DispatchPosCoord,//调货货物库位
                StoragePosCoord = request.StoragePosCoord,//调货货物目标点位
                TargetPointCoord = request.TargetPointCoord,//调货货物目标库位
                TargetFloor = request.TargetFloor,
                Palletcode = request.Palletcode,
                Speed = request.Speed,
                Agvtype = request.Agvtype
            };
        }
        return await CreateDispatchPlan(dispatchRequest);
    }
    //充电
    private async Task<ServiceResult> ProcessRechargeRequest(BaseRequest request)
    {
        if (request is not InboundRequest inboundRequest)
        {
            inboundRequest = new InboundRequest
            {
                TaskId = request.TaskId,
                AgvCode = request.AgvCode,
                AgvCurrentPos = request.AgvCurrentPos,
                Startcoord = request.Startcoord,
                TargetFloor = request.TargetFloor,
                TargetPointCoord = "4,14",
                StoragePosCoord = "4,15",
                Palletcode = request.Palletcode,
                Speed = request.Speed,
                Agvtype = request.Agvtype
            };
        }

        return await CreateRechargePlan(inboundRequest);
    } 
    #endregion

    #region 入库流程
    public async Task<ServiceResult> CreateInboundPlan(InboundRequest request)
    {
        /* currentActionSort = 0; // 重置动作组排序值*/
        ValidateInboundRequest(request);
        var actions = new List<AgvactionsEntity>();

        // 先获取当前最大的AgvTaskid
        int initialAgvTaskid = await GetNextAgvTaskid();
        int currentAgvTaskid = initialAgvTaskid;

        // 1. 提升机动作（提升机升货）
        currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateHoistAction(request, ActionTypeEnum.HoistOperationup, startPos)
        );

        // 2. 取货动作 - 调用路径规划并手动添加动作
        var pickupStartPos = actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos;
        var pickupActions = await GeneratePickupActionWithPathPlanning(request, ActionTypeEnum.Pickup, request.AgvCurrentPos);

        // 添加路径规划生成的动作及反馈动作
        foreach (var action in pickupActions)
        {
            currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                startPos => action
            );

        }

        // 3. 举货动作
        currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos)
        );

        // 4. 路径规划到目标库位点位
        var deliveryActions = await PlanStorageDelivery(request,
            ActionTypeEnum.StorageDelivery,
            actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos,
            request.TargetPointCoord);

        foreach (var action in deliveryActions)
        {
            currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid, 
                startPos => action
            );
            //每个直线动作后都执行举货
            currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
           startPos => SongGenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos, (int)(actions.LastOrDefault()?.Actionsort))
      );

        }
        /*   //5入库位前举货
           var beforeLiftingStartPos = actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos;
           currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
               startPos => GenerateEnterStorageAction(request,ActionTypeEnum.BeforeLifting, startPos)
           );*/

        // 6. 进入库位动作
        currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateEnterStorageAction(request, ActionTypeEnum.InLocation, startPos)
        );

        // 7. 卸货动作
        currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateUnloadingAction(request, ActionTypeEnum.Unloading, startPos)
        );

        // 8. 返回可行走坐标
        currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateReturnPointAction(request, ActionTypeEnum.OutLocation, startPos)
        );

        await _agvactionsRepo.InsertRangeAsync(actions);
        Console.WriteLine($"生成{actions.Count}条入库动作，初始AgvTaskid: {initialAgvTaskid}，最终AgvTaskid: {currentAgvTaskid - 1}");
        return ServiceResult.Success($"生成{actions.Count}条入库动作（含反馈）");
    }
    #endregion

    #region 出库
    public async Task<ServiceResult> CreateOutboundPlan(OutboundRequest request)
    {
        /*currentActionSort = 0; // 重置动作组排序值*/
        ValidateOutboundRequest(request);
        var actions = new List<AgvactionsEntity>();
        int initialAgvTaskid = await GetNextAgvTaskid();
        int currentAgvTaskid = initialAgvTaskid;

        // 1. 从AGV当前位置移动到目标可行走坐标（Pickup动作） - 使用路径规划
        var pickupStartPos = actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos;
        var pickupActions = await GeneratePickupActionWithPathPlanning(request, ActionTypeEnum.Pickup, request.AgvCurrentPos);

        // 添加路径规划生成的动作及反馈动作
        foreach (var action in pickupActions)
        {
            currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                startPos => action
            );
        }


        // 2. 进入源库位（InLocation动作）
        currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateEnterStorageAction(request, ActionTypeEnum.InLocation, startPos)
        );

        // 3. 举货动作（Lifting动作）
        currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos)
        );

        // 4. 返回可行走区域（OutLocation动作） - 使用出库专用方法
        currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateOutboundReturnPointAction(request, ActionTypeEnum.OutLocation, startPos)
        );

        // 5. 送货到提升机位置（Delivery动作）
        string targetHoistPoint = CalculateHoistTargetPoint(request.ExitPos, request.TargetFloor);
        (int x, int y) = GetCoordinateByPointPrefix(targetHoistPoint);
        string targetHoistCoord = $"{x},{y}";

        var deliveryActions = await PlanPath(request, ActionTypeEnum.Delivery,
            request.TargetPointCoord, targetHoistCoord);

        foreach (var action in deliveryActions)
        {
            currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                startPos => action
            );
            //每个直线动作后都执行举货
            currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
           startPos => SongGenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos, (int)(actions.LastOrDefault()?.Actionsort)));
        }

        // 6. 卸货动作（Unloading动作）
        currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateUnloadingAction(request, ActionTypeEnum.Unloading, startPos)
        );
        string ss = actions.OrderByDescending(x => x.Id).Take(1).Select(c => c.StartPosition).First();
        /*      request.TargetPointCoord = ss;*/

        // 7. 提升机下货动作（HoistOperationdown动作）
        currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateHoistAction(request, ActionTypeEnum.HoistOperationdown, startPos)
        );


        await _agvactionsRepo.InsertRangeAsync(actions);
        Console.WriteLine($"生成{actions.Count}条出库动作，初始AgvTaskid: {initialAgvTaskid}，最终AgvTaskid: {currentAgvTaskid - 1}");
        return ServiceResult.Success($"生成{actions.Count}条出库动作（含反馈）");
    }
    #endregion
    #region  充电
    public async Task<ServiceResult> CreateRechargePlan(InboundRequest request)
    {
        /* currentActionSort = 0; // 重置动作组排序值*/
        //ValidateInboundRequest(request);
        var actions = new List<AgvactionsEntity>();

        // 先获取当前最大的AgvTaskid
        int initialAgvTaskid = await GetNextAgvTaskid();
        int currentAgvTaskid = initialAgvTaskid;
        // 2. 充电动作 - 调用路径规划并手动添加动作
        var deliveryActions = await PlanStorageDelivery(request,
           ActionTypeEnum.StorageDelivery,
           actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos,
           request.TargetPointCoord);

        foreach (var action in deliveryActions)
        {
            currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                startPos => action
            );
        }
        //  进入库位动作(充电位置)
        currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateEnterStorageAction(request, ActionTypeEnum.InLocation, startPos)
        );
        //  充电动作
        currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
            startPos => GenerateEnterStorageAction(request, ActionTypeEnum.recharge, startPos)
        );
        await _agvactionsRepo.InsertRangeAsync(actions);
        return ServiceResult.Success($"生成{actions.Count}条充电动作（含反馈）");
    }

    #endregion
    #region 调货
    [ApiDescriptionSettings(Name = "CreateDispatchPlanNew"), HttpPost]
    public async Task<ServiceResult> CreateDispatchPlan(DispatchRequest request)
    {
        ValidateDispatchRequest(request);
        var actions = new List<AgvactionsEntity>();
        int currentAgvTaskid = await GetNextAgvTaskid();
        int currentActionSort = 0;

        // 1. 从当前位置到调货货物点位（路径规划+反馈，无举货）
        var pickupPathActions = await GenerateDispatchPathActions(
            request,
            ActionTypeEnum.Pickup,
            request.AgvCurrentPos,
            request.DispatchCoord,
            currentAgvTaskid,
             currentActionSort
        );
        actions.AddRange(pickupPathActions);
        currentAgvTaskid++;

        // 2. 进入源库位（举货前移动+反馈）
        var enterSourceStartPos = actions.LastOrDefault()?.TargetPosition ?? request.DispatchCoord;
        var enterSourceAction = GenerateDispatchEnterStorageAction(
            request,
            ActionTypeEnum.InLocation,
            enterSourceStartPos,
            currentAgvTaskid,
            currentActionSort++
        );
        actions.Add(enterSourceAction);
        actions.Add(GenerateFeedbackAction(enterSourceAction, currentActionSort++));

        // 3. 举货动作（单点+反馈）
        var liftingAction = GenerateDispatchLiftingAction(
            request,
            enterSourceAction.TargetPosition,
            currentAgvTaskid,
            currentActionSort++
        );
        actions.Add(liftingAction);
        actions.Add(GenerateFeedbackAction(liftingAction, currentActionSort++));
        currentAgvTaskid++;

        // 4. 返回调货货物点位（路径规划+反馈，无举货）
        var returnSourcePathActions = await GenerateDispatchPathActions(
            request,
            ActionTypeEnum.OutLocation,
            liftingAction.TargetPosition,
            request.DispatchCoord,
            currentAgvTaskid,
             currentActionSort
        );
        actions.AddRange(returnSourcePathActions);
        currentAgvTaskid++;

        // 5. 从调货货物点位到目标货物点位（路径规划+每段举货+反馈）
        var deliveryPathActions = await GenerateDispatchPathActions(
            request,
            ActionTypeEnum.Delivery,
            request.DispatchCoord,
            request.TargetPointCoord,
            currentAgvTaskid,
            currentActionSort,
            addLifting: true
        );
        actions.AddRange(deliveryPathActions);
        currentAgvTaskid++;

        // 6. 进入目标库位（卸货前移动+反馈）
        var enterTargetStartPos = actions.LastOrDefault()?.TargetPosition ?? request.TargetPointCoord;
        var enterTargetAction = GenerateDispatchEnterStorageAction(
            request,
            ActionTypeEnum.InLocation,
            enterTargetStartPos,
            currentAgvTaskid,
            currentActionSort++
        );
        actions.Add(enterTargetAction);
        actions.Add(GenerateFeedbackAction(enterTargetAction, currentActionSort++));

        // 7. 卸货动作（单点+反馈）
        var unloadingAction = GenerateDispatchUnloadingAction(
            request,
            enterTargetAction.TargetPosition,
            currentAgvTaskid,
            currentActionSort++
        );
        actions.Add(unloadingAction);
        actions.Add(GenerateFeedbackAction(unloadingAction, currentActionSort++));
        currentAgvTaskid++;

        // 8. 返回目标货物点位（路径规划+反馈，无举货）
        var returnTargetPathActions = await GenerateDispatchPathActions(
            request,
            ActionTypeEnum.OutLocation,
            unloadingAction.TargetPosition,
            request.TargetPointCoord,
            currentAgvTaskid,
            currentActionSort
        );
        actions.AddRange(returnTargetPathActions);

        await _agvactionsRepo.InsertRangeAsync(actions);
        return ServiceResult.Success($"生成{actions.Count}条调货动作");
    }
    #endregion

    #region 提升机动作生成
    private AgvactionsEntity GenerateHoistAction(BaseRequest request, ActionTypeEnum actionGroupType, string startPos)
    {
        ValidateHoistPointFormat(request.Startcoord);
        var targetPointName = CalculateHoistTargetPoint(request.Startcoord, request.TargetFloor);
        var outPointName = ChukuTargetPoint(request.Startcoord, request.TargetFloor);
        switch (startPos)
        {
            case "23,15":
                startPos = "11";
                break;
            case "3,15":
                startPos = "21";
                break;
            case "3,3":
                startPos = "31";
                break;
            case "11,3":
                startPos = "41";
                break;
            case "23,3":
                startPos = "51";
                break;

        }

        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = request.Agvtype == "inbound" ? startPos : outPointName,
            TargetPosition = request.Agvtype == "inbound" ? targetPointName : startPos,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = request.Agvtype == "inbound" ? targetPointName : outPointName,
            Palletcode = request.Palletcode,
            Routepoint = GenerateRoutePoints(startPos, request.Agvtype == "inbound" ? targetPointName : startPos),
            Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
            TargetFloor = request.TargetFloor
        };

        currentActionSort++; // 每个动作组排序值递增
        return action;
    }
    //入库计算 提升机位置
    private string CalculateHoistTargetPoint(string startPoint, int targetFloor)
    {
        if (!Regex.IsMatch(startPoint, @"^\d\d$"))
        {
            throw new CustomFriendlyException($"提升机点位格式错误：{startPoint}");
        }

        var prefixDigit = startPoint[0];
        var lastTwoDigits = int.Parse(startPoint.Substring(1));
        var targetLastTwoDigits = lastTwoDigits + 3 + targetFloor;

        if (targetLastTwoDigits > 99)
        {
            throw new CustomFriendlyException($"楼层过高，导致点位超出范围：{startPoint} + {targetFloor}");
        }

        return $"{prefixDigit}{targetLastTwoDigits}";
    }
    //出库计算提升机位置
    private string ChukuTargetPoint(string startPoint, int targetFloor)
    {
        if (!Regex.IsMatch(startPoint, @"^\d\d$"))
        {
            throw new CustomFriendlyException($"提升机点位格式错误：{startPoint}");
        }

        var prefixDigit = startPoint[0];
        var lastTwoDigits = int.Parse(startPoint.Substring(1));
        var targetLastTwoDigits = lastTwoDigits + 4 + targetFloor;

        if (targetLastTwoDigits > 99)
        {
            throw new CustomFriendlyException($"楼层过高，导致点位超出范围：{startPoint} + {targetFloor}");
        }

        return $"{prefixDigit}{targetLastTwoDigits}";
    }

    private (int x, int y) GetCoordinateByPointPrefix(string targetPoint)
    {
        if (string.IsNullOrEmpty(targetPoint) || targetPoint.Length < 1)
        {
            throw new CustomFriendlyException($"无效的点位名称：{targetPoint}");
        }

        var firstDigit = int.Parse(targetPoint[0].ToString());
        return firstDigit switch
        {
            1 => (23, 15),
            2 => (3, 15),
            3 => (3, 3),
            4 => (11, 3),
            5 => (23, 3),
            _ => throw new CustomFriendlyException($"不支持的点位类型：{firstDigit}（仅支持1-5开头）")
        };
    }
    #endregion

    #region 出库动作 调用
    private AgvactionsEntity GenerateOutboundReturnPointAction(OutboundRequest request, ActionTypeEnum actionGroupType, string startPos)
    {
        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = request.TargetPointCoord,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = request.TargetPointCoord,
            Palletcode = request.Palletcode,
            Routepoint = GenerateRoutePoints(startPos, request.TargetPointCoord),
            Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
            TargetFloor = request.TargetFloor
        };

        currentActionSort++; // 每个动作组排序值递增
        return action;
    }

    private async Task<int> CreateOutboundChainedActionGroup(
        List<AgvactionsEntity> allActions,
        OutboundRequest request,
        int currentAgvTaskid,
        params Func<string, AgvactionsEntity>[] actionGenerators)
    {
        string prevTarget = allActions.Any() ? allActions.Last().TargetPosition : request.AgvCurrentPos;

        foreach (var generator in actionGenerators)
        {
            var action = generator(prevTarget);
            action.AgvTaskid = currentAgvTaskid;
            allActions.Add(action);

            var feedback = GenerateFeedbackAction(action, action.ActionGroupType);
            feedback.AgvTaskid = currentAgvTaskid;
            allActions.Add(feedback);

            prevTarget = action.TargetPosition;
            currentAgvTaskid++;
        }

        return currentAgvTaskid;
    }
    #endregion

    #region 库位进出动作生成
    private AgvactionsEntity GenerateEnterStorageAction(BaseRequest request, ActionTypeEnum actionGroupType, string startPos)
    {
        var storagePos = request is InboundRequest inbound
            ? inbound.StoragePosCoord
            : ((OutboundRequest)request).SourceStoragePosCoord;

        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = storagePos,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = storagePos,
            Palletcode = request.Palletcode,
            Routepoint = GenerateRoutePoints(startPos, storagePos),
            Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
            TargetFloor = request.TargetFloor
        };

        currentActionSort++; // 每个动作组排序值递增
        return action;
    }

    private AgvactionsEntity GenerateReturnPointAction(BaseRequest request, ActionTypeEnum actionGroupType, string startPos)
    {
        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = request.TargetPointCoord,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = request.TargetPointCoord,
            Palletcode = request.Palletcode,
            Routepoint = GenerateRoutePoints(startPos, request.TargetPointCoord),
            Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
            TargetFloor = request.TargetFloor
        };

        currentActionSort++; // 每个动作组排序值递增
        return action;
    }
    #endregion

    #region 基础动作生成
    private async Task<List<AgvactionsEntity>> GeneratePickupActionWithPathPlanning(BaseRequest request, ActionTypeEnum actionGroupType, string startPos)
    {
        string targetPos;

        if (request is OutboundRequest outboundRequest)
        {
            if (request.Agvtype == "Dispatch")
            {
                // 出库场景：从当前位置移动到目标可行走坐标
                targetPos = outboundRequest.DispatchCoord;
            }
            // 出库场景：从当前位置移动到目标可行走坐标
            targetPos = outboundRequest.TargetPointCoord;
        }
        else
        {
            // 入库场景：从当前位置移动到提升机位置
            targetPos = GetHoistTargetPosition(request);
        }

        // 起点与终点相同，直接返回单个动作
        if (startPos == targetPos)
        {
            return new List<AgvactionsEntity> { GenerateSinglePickupAction(request, actionGroupType, startPos, targetPos) };
        }

        // 调用路径规划获取直线段动作
        return await PlanPath(request, actionGroupType, startPos, targetPos);
    }

    private AgvactionsEntity GenerateSinglePickupAction(BaseRequest request, ActionTypeEnum actionGroupType, string startPos, string targetPos)
    {
        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = targetPos,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = targetPos,
            Palletcode = request.Palletcode,
            Routepoint = GenerateRoutePoints(startPos, targetPos),
            Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
            TargetFloor = request.TargetFloor
        };

        currentActionSort++; // 每个动作组排序值递增
        return action;
    }

    private string GetHoistTargetPosition(BaseRequest request)
    {
        ValidateHoistPointFormat(request.Startcoord);
        var targetPointName = CalculateHoistTargetPoint(request.Startcoord, request.TargetFloor);
        var (x, y) = GetCoordinateByPointPrefix(targetPointName);
        return $"{x},{y}";
    }

    /// <summary>
    /// 送货途径中举货
    /// </summary>
    /// <param name="request"></param>
    /// <param name="actionGroupType"></param>
    /// <param name="startPos"></param>
    /// <returns></returns>
    private AgvactionsEntity SongGenerateLiftingAction(BaseRequest request, ActionTypeEnum actionGroupType, string startPos, int Actionsort)
    {
        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = startPos,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = startPos,
            Palletcode = request.Palletcode,
            Routepoint = startPos, // 举货动作只有一个点位
            Actionsort = AgainSort == 0 ? Actionsort : AgainSort,
            TargetFloor = request.TargetFloor
        };
        return action;
    }
    /// <summary>
    /// 举货动作添加
    /// </summary>
    /// <param name="request"></param>
    /// <param name="actionGroupType"></param>
    /// <param name="startPos"></param>
    /// <returns></returns>
    private AgvactionsEntity GenerateLiftingAction(BaseRequest request, ActionTypeEnum actionGroupType, string startPos)
    {
        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = startPos,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = startPos,
            Palletcode = request.Palletcode,
            Routepoint = startPos, // 举货动作只有一个点位
            Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
            TargetFloor = request.TargetFloor
        };

        currentActionSort++; // 每个动作组排序值递增
        return action;
    }

    private AgvactionsEntity GenerateUnloadingAction(BaseRequest request, ActionTypeEnum actionGroupType, string startPos)
    {
        var action = new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = startPos,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = startPos,
            Palletcode = request.Palletcode,
            Routepoint = startPos, // 卸货动作只有一个点位
            Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
            TargetFloor = request.TargetFloor
        };

        currentActionSort++; // 每个动作组排序值递增
        return action;
    }
    #endregion

    #region 路径规划
    private async Task<List<AgvactionsEntity>> PlanPath(BaseRequest request, ActionTypeEnum groupType, string startCoord, string targetCoord)
    {
        if (request == null) throw new ArgumentNullException(nameof(request));
        if (string.IsNullOrEmpty(startCoord)) throw new ArgumentException("起始坐标不能为空", nameof(startCoord));
        if (string.IsNullOrEmpty(targetCoord)) throw new ArgumentException("目标坐标不能为空", nameof(targetCoord));
        if (!IsValidCoordinate(startCoord)) throw new CustomFriendlyException($"无效的起始坐标格式: {startCoord}");
        if (!IsValidCoordinate(targetCoord)) throw new CustomFriendlyException($"无效的目标坐标格式: {targetCoord}");

        var start = ParseCoordinate(startCoord);
        var end = ParseCoordinate(targetCoord);

        if (string.IsNullOrEmpty(request.AgvCode))
            throw new ArgumentException("AGV编号不能为空", nameof(request.AgvCode));
       
        var vehicle = new Vehicle(request.AgvCode, request.TargetFloor, (start.X, start.Y), (end.X, end.Y), request.Speed);
        // 调用RCS服务进行路径规划
        var response = await _rcsService.QueryAsync(new List<Vehicle> { vehicle });
        //调用路径规划返回数据
        SerilogHelper.WriteLog("DispatchServiceAndPlanPath", "select", JsonHelper.ObjectToJson(response));
        //路线数据存redis(+"Point")


        var redisKey = request.AgvCode+"Point";
        var json = _sysCacheService.Get<string>(redisKey);
        //activeBlockedPoints = _sysCacheService.Get<List<(int x,int y)>>(x.DeviceId);
        //先获取redis的数据
        List<(int x, int y)> Points = JsonHelper.JsonToObject<List<(int x, int y)>>(json);
        //然后通任务的所有点位累加
        List<(int x,int y)> values = response.Result[0].Path;
        if(json!=null)
        {
            foreach (var item in values)
            {
                Points.Add(item);
            }
            var jsonValue = JsonConvert.SerializeObject(Points);
            _sysCacheService.Set(redisKey, jsonValue);
            var ss = _sysCacheService.Get<List<(int X, int Y)>>(request.AgvCode);
        }
        else
        {
            var jsonValue = JsonConvert.SerializeObject(values);
            _sysCacheService.Set(redisKey, jsonValue);
            var ss = _sysCacheService.Get<List<(int X, int Y)>>(request.AgvCode);
        }
           
        //var lists = _sysCacheService.Get<string>(redisKey);
        if (response.Code != 200 || !response.Result.Any()) 
        {
            throw new CustomFriendlyException($"路径规划失败: {response.Message}");
        }

        var path = response.Result[0].Path.Select(p => $"{p.X},{p.Y}").ToList();
        var mergedSegments = MergeCollinearPoints(path);

        var actions = new List<AgvactionsEntity>();

        foreach (var segment in mergedSegments)
        {
            var action = new AgvactionsEntity
            {
                TaskId = request.TaskId,
                DeviceId = request.AgvCode,
                ActionType = AgvActionType.Movement,
                StartPosition = segment.First(),
                TargetPosition = segment.Last(),
                Status = ActionStatusEnum.Pending,
                ActionGroupType = groupType,
                Istype = request.Agvtype,
                GroupStartPosition = path.First(),
                GroupTargetPosition = path.Last(),
                Palletcode = request.Palletcode,
                Routepoint = JsonSerializer.Serialize(segment),// 路径点列表包含线段上的所有点位
                Actionsort = AgainSort == 0 ? currentActionSort : AgainSort,
                TargetFloor = request.TargetFloor
            };


            actions.Add(action);
        }

        currentActionSort++; // 路径规划动作作为一个组，排序值递增一次
        return actions;
    }

    private async Task<List<AgvactionsEntity>> PlanStorageDelivery(BaseRequest request, ActionTypeEnum groupType, string startCoord, string targetCoord)
    {
        return await PlanPath(request, groupType, startCoord, targetCoord);
    }
    #endregion

    #region 工具方法（坐标处理）
    private Point ParseCoordinate(string coordStr)
    {
        if (!IsValidCoordinate(coordStr)) throw new CustomFriendlyException($"无效的坐标格式：{coordStr}（示例：24,12）");
        var parts = coordStr.Split(',');
        return new Point { X = int.Parse(parts[0]), Y = int.Parse(parts[1]) };
    }

    private List<List<string>> MergeCollinearPoints(List<string> pathPoints)
    {
        var mergedSegments = new List<List<string>>();
        if (pathPoints.Count == 0) return mergedSegments;

        var currentSegment = new List<string> { pathPoints[0] };
        for (int i = 1; i < pathPoints.Count; i++)
        {
            if (currentSegment.Count < 2)
            {
                currentSegment.Add(pathPoints[i]);
                continue;
            }

            var p1 = ParseCoordinate(currentSegment[^2]);
            var p2 = ParseCoordinate(currentSegment[^1]);
            var p3 = ParseCoordinate(pathPoints[i]);

            long crossProduct = (long)(p2.X - p1.X) * (p3.Y - p2.Y) - (long)(p2.Y - p1.Y) * (p3.X - p2.X);
            if (crossProduct == 0)
            {
                currentSegment.Add(pathPoints[i]);
            }
            else
            {
                mergedSegments.Add(currentSegment);
                currentSegment = new List<string> { currentSegment[^1], pathPoints[i] };
            }
        }

        if (currentSegment.Count >= 2)
        {
            mergedSegments.Add(currentSegment);
        }

        return mergedSegments;
    }

    private bool IsValidCoordinate(string coordStr)
    {
        if (string.IsNullOrEmpty(coordStr))
            return false;

        // 允许坐标格式（如 "23,15"）或提升机点位格式（如 "12"）
        var coordinatePattern = @"^\d+,\d+$";
        var hoistPointPattern = @"^\d\d$";

        return Regex.IsMatch(coordStr, coordinatePattern) ||
               Regex.IsMatch(coordStr, hoistPointPattern);
    }

    // 生成从起点到终点的所有路径点
    private string GenerateRoutePoints(string startPos, string endPos)
    {
        var points = new List<string>();

        // 处理提升机点位的特殊情况
        if (IsHoistPoint(startPos) && IsHoistPoint(endPos) && GetHoistPrefix(startPos) == GetHoistPrefix(endPos))
        {
            int startNum = GetHoistNumber(startPos);
            int endNum = GetHoistNumber(endPos);
            int step = startNum < endNum ? 1 : -1;

            // 修复提升机点位循环条件
            for (int num = startNum; step > 0 ? num <= endNum : num >= endNum; num += step)
            {
                points.Add($"{GetHoistPrefix(startPos)}{num}");
            }
        }
        // 常规坐标处理
        else if (IsValidCoordinate(startPos) && IsValidCoordinate(endPos))
        {
            var start = ParseCoordinate(startPos);
            var end = ParseCoordinate(endPos);

            // 水平移动 - 修复循环条件
            if (start.Y == end.Y)
            {
                int step = start.X < end.X ? 1 : -1;
                for (int x = start.X; step > 0 ? x <= end.X : x >= end.X; x += step)
                {
                    points.Add($"{x},{start.Y}");
                }
            }
            // 垂直移动 - 修复循环条件
            else if (start.X == end.X)
            {
                int step = start.Y < end.Y ? 1 : -1;
                for (int y = start.Y; step > 0 ? y <= end.Y : y >= end.Y; y += step)
                {
                    points.Add($"{start.X},{y}");
                }
            }
            // 斜向移动
            else
            {
                points.Add(startPos);
                points.Add(endPos);
            }
        }
        // 混合格式处理
        else
        {
            points.Add(startPos);
            points.Add(endPos);
            Console.WriteLine($"警告：混合格式路径点 - startPos:{startPos}, endPos:{endPos}");
        }

        // 清理空值
        var cleanedPoints = points
            .Where(p => !string.IsNullOrWhiteSpace(p))
            .ToList();

        // 确保至少有一个点
        if (!cleanedPoints.Any())
        {
            cleanedPoints.Add("unknown");
        }

        // 序列化
        try
        {
            string jsonString = JsonSerializer.Serialize(cleanedPoints);
            Console.WriteLine($"最终生成路径点 JSON: {jsonString}");
            return jsonString;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"路径点序列化失败: {ex.Message}");
            return "[\"error\"]";
        }
    }
    // 判断是否为提升机点位（如 "12"）
    private bool IsHoistPoint(string pos)
    {
        return Regex.IsMatch(pos, @"^\d\d$");
    }

    // 获取提升机点位的前缀（如 "12" 的前缀是 "1"）
    private string GetHoistPrefix(string hoistPos)
    {
        return hoistPos.Substring(0, 1);
    }

    // 获取提升机点位的数字部分（如 "12" 的数字是 2）
    private int GetHoistNumber(string hoistPos)
    {
        return int.Parse(hoistPos.Substring(1));
    }
    #endregion

    #region 请求校验
    private void ValidateInboundRequest(InboundRequest request)
    {
        ValidateBaseRequest(request);
        if (!IsValidCoordinate(request.TargetPointCoord)) throw new CustomFriendlyException($"入库目标可行走坐标格式错误：{request.TargetPointCoord}");
        if (!IsValidCoordinate(request.StoragePosCoord)) throw new CustomFriendlyException($"入库目标库位坐标格式错误：{request.StoragePosCoord}");
    }

    private void ValidateOutboundRequest(OutboundRequest request)
    {
        ValidateBaseRequest(request);
        if (!IsValidCoordinate(request.TargetPointCoord)) throw new CustomFriendlyException($"出库目标可行走坐标格式错误：{request.TargetPointCoord}");
        if (!IsValidCoordinate(request.SourceStoragePosCoord)) throw new CustomFriendlyException($"出库源库位坐标格式错误：{request.SourceStoragePosCoord}");
        if (!IsValidCoordinate(request.ExitPos)) throw new CustomFriendlyException($"出库终点坐标格式错误：{request.ExitPos}");
    }

    private void ValidateBaseRequest(BaseRequest request)
    {
        if (string.IsNullOrEmpty(request.TaskId)) throw new CustomFriendlyException("任务ID不能为空");
        if (string.IsNullOrEmpty(request.AgvCode)) throw new CustomFriendlyException("AGV编号不能为空");
        if (string.IsNullOrEmpty(request.AgvCurrentPos)) throw new CustomFriendlyException("AGV当前位置不能为空");
        //if (string.IsNullOrEmpty(request.Startcoord)) throw new CustomFriendlyException("起始位置Startcoord不能为空");
        if (request.TargetFloor < 1) throw new CustomFriendlyException("目标楼层必须≥1");
        //if (string.IsNullOrEmpty(request.Agvtype) || !new[] { "inbound", "outbound" }.Contains(request.Agvtype.ToLower()))
        //{
        //    throw new CustomFriendlyException("Agvtype字段必须为'inbound'或'outbound'");
        //}
        if (!IsValidCoordinate(request.Startcoord)) throw new CustomFriendlyException($"起始位置Startcoord格式错误（示例：24,12）");
        if (!IsValidCoordinate(request.AgvCurrentPos) && !IsValidHoistPoint(request.AgvCurrentPos))
        {
            throw new CustomFriendlyException($"AGV当前位置格式错误（应为坐标或提升机点位）");
        }
    }

    private bool IsValidHoistPoint(string point)
    {
        try { ValidateHoistPointFormat(point); return true; } catch { return false; }
    }

    private void ValidateHoistPointFormat(string point)
    {
        if (!Regex.IsMatch(point, @"^\d{1}\d{1}$"))
        {
            throw new CustomFriendlyException($"提升机点位格式错误：{point}");
        }
    }
    #endregion

    #region 反馈动作生成
    private AgvactionsEntity GenerateFeedbackAction(AgvactionsEntity originalAction, ActionTypeEnum actionGroupType)
    {
        return new AgvactionsEntity
        {
            TaskId = originalAction.TaskId,
            DeviceId = originalAction.DeviceId,
            ActionType = AgvActionType.Feedback,
            StartPosition = originalAction.StartPosition,
            TargetPosition = originalAction.TargetPosition,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = originalAction.Istype,
            GroupStartPosition = originalAction.GroupStartPosition,
            GroupTargetPosition = originalAction.GroupTargetPosition,
            Palletcode = originalAction.Palletcode,
            Routepoint = originalAction.TargetPosition,
            TargetFloor = originalAction.TargetFloor,
            Actionsort = originalAction.Actionsort // 反馈动作与主动作使用相同排序值
        };
    }
    #endregion

    #region 辅助方法（链式动作组生成）
    private async Task<int> CreateChainedActionGroup(
     List<AgvactionsEntity> allActions,
     BaseRequest request,
     int currentAgvTaskid,
     params Func<string, AgvactionsEntity>[] actionGenerators)
    {
        string prevTarget = allActions.Any() ? allActions.Last().TargetPosition : request.Startcoord;

        foreach (var generator in actionGenerators)
        {
            var action = generator(prevTarget);

            // 验证 Routepoint 能否正确序列化为 JSON
            try
            {
                //去掉所有的双引号

                /*var json = JsonSerializer.Serialize(action.Routepoint);
                 action.Routepoint =  json;
                Console.WriteLine($"路径点 JSON 序列化结果: {json}");*/
                string jsonToStore = action.Routepoint;
                Console.WriteLine($"正确存储的 JSON: {jsonToStore}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"路径点 JSON 序列化失败: {ex.Message}");
                // 记录问题路径点并设置默认值
                Console.WriteLine($"问题路径点: {string.Join(", ", action.Routepoint)}");
                //action.Routepoint = new Liststring> { "error" };   
            }

            action.AgvTaskid = currentAgvTaskid;
            allActions.Add(action);

            var feedback = GenerateFeedbackAction(action, action.ActionGroupType);
            feedback.AgvTaskid = currentAgvTaskid;
            allActions.Add(feedback);

            prevTarget = action.TargetPosition;
            currentAgvTaskid++;
        }

        return currentAgvTaskid;
    }
    #endregion

    #region AgvTaskid生成器
    private async Task<int> GetNextAgvTaskid()
    {
        await _taskIdLock.WaitAsync();
        try
        {
            var maxTaskid = await _agvactionsRepo.AsQueryable()
               .Where(a => a.Status == ActionStatusEnum.Completed || a.Status == ActionStatusEnum.Pending)
               .MaxAsync(a => a.AgvTaskid);

            int nextId = maxTaskid.HasValue ? maxTaskid.Value + 1 : 10000;
            Console.WriteLine($"从数据库获取的下一个AgvTaskid: {nextId}");
            return nextId > 99999 ? 10000 : nextId;
        }
        finally
        {
            _taskIdLock.Release();
        }
    }
    #endregion

    // 自定义异常类
    public class CustomFriendlyException : Exception
    {
        public CustomFriendlyException(string message) : base(message) { }
    }

    /// <summary>
    /// 查询agv任务步骤
    /// </summary>
    /// <param name="agvations"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "GetAgvActionPageList"), HttpPost]
    public async Task<SqlSugarPagedList<AgvactionsEntity>> GetAgvActionPageList(AgvationsDto agvations)
    {
        SerilogHelper.WriteLog("DispathService——查询agv任务步骤开始" + JsonConvert.SerializeObject(agvations));

        var list = await _agvactionsRepo.AsQueryable()
         .WhereIF(!string.IsNullOrWhiteSpace(agvations.TaskId), u => u.TaskId.Contains(agvations.TaskId))
         .WhereIF(!string.IsNullOrWhiteSpace(agvations.DeviceId), u => u.DeviceId.Contains(agvations.DeviceId))
         .WhereIF(!string.IsNullOrWhiteSpace(agvations.ActionType.ToString()), u => u.ActionType.Equals(agvations.ActionType))
            //.WhereIF(!string.IsNullOrWhiteSpace(agvations.StartPosition.ToString()), u => u.StartPosition.Equals(agvations.StartPosition))
            //.WhereIF(!string.IsNullOrWhiteSpace(agvations.TargetPosition.ToString()), u => u.TargetPosition.Equals(agvations.TargetPosition))

            .OrderBuilder(agvations)
            .ToPagedListAsync(agvations.Page, agvations.PageSize);
        SerilogHelper.WriteLog("DispathService——查询agv任务步骤结束" + JsonConvert.SerializeObject(list));

        return list;
    }
    #endregion

    /// <summary>
    /// 修改下发步骤
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateAgvactions"), HttpPost]
    public async Task UpdateAgvactions(List<UpdateAgvactionsInput> entity)
    {

        SerilogHelper.WriteLog("DispatchService", "UpdateAgvactions", $"修改下发步骤开始: {JsonConvert.SerializeObject(entity)}");
        foreach (var item in entity)
        {
            #region 唯一索引  
            Expression<Func<AgvactionsEntity, bool>> whereExpression = whereExp =>
                        whereExp.Id.Equals(item.Id);
            #endregion
            var Inventory = await _agvactionsRepo.GetFirstAsync(u => u.Id == item.Id);

            try
            {
                if (Inventory != null)
                {

                    if (Inventory.Status == ActionStatusEnum.Pending)
                    {
                        //待处理转为已取消 取消操作
                        Inventory.Status = ActionStatusEnum.Cancelled;
                    }
                    if (Inventory.Status == ActionStatusEnum.Cancelled)
                    {
                        // 已取消转为待处理 启动操作
                        Inventory.Status = ActionStatusEnum.Pending;

                    }
                    // 更新用户信息  
                    Inventory.UpdateUserId = _usermanager.UserId;
                    Inventory.UpdateTime = DateTime.Now;
                    Inventory.UpdateUserName = _usermanager.RealName;



                }
                else
                {
                    SerilogHelper.WriteLog("UpdateInventory查询不到核对状态" + ErrorCodeEnum.D1002);
                    throw Oops.Oh(ErrorCodeEnum.D1002);
                }
            }
            catch (Exception error)
            {
                SerilogHelper.WriteLog("DispatchService", "UpdateAgvactions", $"修改库存管理结束: {JsonConvert.SerializeObject(error.Message)}");
                throw Oops.Oh("修改出现错误：" + error.Message + "");
            }
            var invtirt = Inventory.Adapt<AgvactionsEntity>();
            SerilogHelper.WriteLog("DispatchService", "UpdateAgvactions", $"修改库存管理结束: {JsonConvert.SerializeObject(invtirt)}");
            await _agvactionsRepo.AsUpdateable(invtirt).IgnoreColumns(true).ExecuteCommandAsync();

        }
    }

    #region 重新分配路线
    /// <summary>
    /// 再次分配入库
    /// </summary>
    /// <param name="request"></param>
    /// <param name="x"></param>
    /// <returns></returns>
    public async Task<ServiceResult> AgainInboundRequest(BaseRequest request, int cars, int againsort)
    {
        if (request is not InboundRequest inboundRequest)
        {
            inboundRequest = new InboundRequest
            {
                TaskId = request.TaskId,
                AgvCode = request.AgvCode,
                AgvCurrentPos = request.AgvCurrentPos,
                Startcoord = request.Startcoord,
                TargetFloor = request.TargetFloor,
                TargetPointCoord = request.TargetPointCoord,
                StoragePosCoord = request.StoragePosCoord,
                Palletcode = request.Palletcode,
                Speed = request.Speed,
                Agvtype = request.Agvtype
            };
        }

        return await AgainCreateInboundPlan(inboundRequest, cars, againsort);
    }
    /// <summary>
    /// 再次分配出库
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cars"></param>
    /// <returns></returns>
    public async Task<ServiceResult> AgainOutboundRequest(BaseRequest request, int cars, int againsort)
    {
        if (request is not OutboundRequest outboundRequest)
        {
            outboundRequest = new OutboundRequest
            {
                TaskId = request.TaskId,
                AgvCode = request.AgvCode,
                AgvCurrentPos = request.AgvCurrentPos,
                Startcoord = request.Startcoord, // 提升机标识（如：102）
                TargetFloor = request.TargetFloor,
                SourceStoragePosCoord = request.StoragePosCoord, // 源库位坐标
                ExitPos = request.Startcoord, // 提升机标识
                Palletcode = request.Palletcode,
                Speed = request.Speed,
                Agvtype = request.Agvtype,
                TargetPointCoord = request.TargetPointCoord // 目标可行走坐标
            };
        }

        return await AgainCreateOutboundPlan(outboundRequest, cars, againsort);
    }

    #region 入库流程
    public async Task<ServiceResult> AgainCreateInboundPlan(InboundRequest request, int cars, int againsort)
    {
        ValidateInboundRequest(request);
        var actions = new List<AgvactionsEntity>();

        // 先获取当前最大的AgvTaskid
        int initialAgvTaskid = await GetNextAgvTaskid();
        int currentAgvTaskid = initialAgvTaskid;
        AgainSort = againsort;
        switch (cars)
        {
            case 0:
                // 1. 提升机动作（提升机升货）
                currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateHoistAction(request, ActionTypeEnum.HoistOperationup, startPos)
                );
                break;
            case 1:
                // 2. 取货动作 - 调用路径规划并手动添加动作
                var pickupStartPos = actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos;
                var pickupActions = await GeneratePickupActionWithPathPlanning(request, ActionTypeEnum.Pickup, request.AgvCurrentPos);

                // 添加路径规划生成的动作及反馈动作
                foreach (var action in pickupActions)
                {
                    currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                        startPos => action
                    );
                }
                break;
            case 2:
                // 3. 举货动作
                currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos)
                );
                break;
            case 3:
                // 4. 路径规划到目标可行走坐标
                var deliveryActions = await PlanStorageDelivery(request,
            ActionTypeEnum.StorageDelivery,
            actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos,
            request.TargetPointCoord);

                foreach (var action in deliveryActions)
                {
                    currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                        startPos => action
                    );
                    //每个直线动作后都执行举货
                    currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                   startPos => SongGenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos, (int)(actions.LastOrDefault()?.Actionsort))
              );
                }
                break;
            case 4:
                // 6. 卸货动作
                currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateUnloadingAction(request, ActionTypeEnum.Unloading, startPos)
                );
                break;
            case 7:
                // 5. 进入库位动作
                currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateEnterStorageAction(request, ActionTypeEnum.InLocation, startPos)
                );
                break;
            case 8:
                // 7. 返回可行走坐标
                currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateReturnPointAction(request, ActionTypeEnum.OutLocation, startPos)
                );
                break;
        }
        await _agvactionsRepo.InsertRangeAsync(actions);
        AgainSort = 0;
        Console.WriteLine($"生成{actions.Count}条入库动作，初始AgvTaskid: {initialAgvTaskid}，最终AgvTaskid: {currentAgvTaskid - 1}");
        return ServiceResult.Success($"生成{actions.Count}条入库动作（含反馈）");
    }
    #endregion

    #region 出库

    public async Task<ServiceResult> AgainCreateOutboundPlan(OutboundRequest request, int cars, int againsort)
    {
        ValidateOutboundRequest(request);
        var actions = new List<AgvactionsEntity>();
        int initialAgvTaskid = await GetNextAgvTaskid();
        int currentAgvTaskid = initialAgvTaskid;
        //传回排序字段
        AgainSort = againsort;

        switch (cars)
        {
            case 1:
                // 1. 从AGV当前位置移动到目标可行走坐标（Pickup动作） - 使用路径规划
                var pickupStartPos = actions.Any() ? actions.Last().TargetPosition : request.AgvCurrentPos;
                var pickupActions = await GeneratePickupActionWithPathPlanning(request, ActionTypeEnum.Pickup, request.AgvCurrentPos);

                // 添加路径规划生成的动作及反馈动作
                foreach (var action in pickupActions)
                {
                    currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                        startPos => action
                    );
                }
                break;
            case 3:
                // 2. 进入源库位（InLocation动作）
                currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateEnterStorageAction(request, ActionTypeEnum.InLocation, startPos)
                );
                break;
            case 2:
                // 3. 举货动作（Lifting动作）
                currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos)
                );
                break;
            case 8:
                // 4. 返回可行走区域（OutLocation动作） - 使用出库专用方法
                currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateOutboundReturnPointAction(request, ActionTypeEnum.OutLocation, startPos)
                );
                break;
            case 5:
                // 5. 送货到提升机位置（Delivery动作）
                string targetHoistPoint = CalculateHoistTargetPoint(request.ExitPos, request.TargetFloor);
                (int x, int y) = GetCoordinateByPointPrefix(targetHoistPoint);
                string targetHoistCoord = $"{x},{y}";

                var deliveryActions = await PlanPath(request, ActionTypeEnum.Delivery,
                    request.TargetPointCoord, targetHoistCoord);

                foreach (var action in deliveryActions)
                {
                    currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                        startPos => action
                    );
                    //每个直线动作后都执行举货
                    currentAgvTaskid = await CreateChainedActionGroup(actions, request, currentAgvTaskid,
                   startPos => SongGenerateLiftingAction(request, ActionTypeEnum.Lifting, startPos, (int)(actions.LastOrDefault()?.Actionsort)));
                }
                break;
            case 4:
                // 6. 卸货动作（Unloading动作）
                currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateUnloadingAction(request, ActionTypeEnum.Unloading, startPos)
                );
                break;
            case 6:
                // 7. 提升机下货动作（HoistOperationdown动作）
                currentAgvTaskid = await CreateOutboundChainedActionGroup(actions, request, currentAgvTaskid,
                    startPos => GenerateHoistAction(request, ActionTypeEnum.HoistOperationdown, startPos)
                );
                break;
        }
        await _agvactionsRepo.InsertRangeAsync(actions);
        AgainSort = 0;
        Console.WriteLine($"生成{actions.Count}条出库动作，初始AgvTaskid: {initialAgvTaskid}，最终AgvTaskid: {currentAgvTaskid - 1}");
        return ServiceResult.Success($"生成{actions.Count}条出库动作（含反馈）");
    }
    #endregion

    #endregion

    #region 路径动作生成（修正参数传递）
    private async Task<List<AgvactionsEntity>> GenerateDispatchPathActions(
        DispatchRequest request,
        ActionTypeEnum actionGroupType,
        string startPos,
        string targetPos,
        int agvTaskid,
         int actionSort,
        bool addLifting = false)
    {
        // 构建BaseRequest对象传递给PlanPath方法
        var baseRequest = new BaseRequest
        {
            AgvCode = request.AgvCode,
            Agvtype = request.Agvtype,
            Palletcode = request.Palletcode,
            // 传递其他必要的BaseRequest属性...
        };

        // 调用PlanPath方法（参数匹配：BaseRequest, ActionTypeEnum, string, string）
        var pathActions = await PlanPath(
            baseRequest,
            actionGroupType, // 传递动作分组类型
            startPos,
            targetPos
        );

        // 后续处理保持不变
        if (pathActions == null || pathActions.Count < 2)
        {
            throw new InvalidOperationException($"路径规划失败：从 {startPos} 到 {targetPos} 的路径点不足");
        }

        var resultActions = new List<AgvactionsEntity>();

        // 遍历生成的路径动作，添加反馈动作
        foreach (var action in pathActions)
        {
            // 检查动作有效性
            if (string.IsNullOrEmpty(action.StartPosition) || string.IsNullOrEmpty(action.TargetPosition))
                continue;

            if (action.StartPosition == action.TargetPosition)
                continue;

            // 保留原始动作
            action.Actionsort = actionSort++;
            action.AgvTaskid = agvTaskid;
            resultActions.Add(action);

            // 添加反馈动作
            resultActions.Add(GenerateFeedbackAction(action, actionSort++));

            // 添加举货动作（如果需要）
            if (addLifting && resultActions.Count < pathActions.Count - 1)
            {
                var liftAction = GenerateDispatchLiftingAction(
                    request,
                    action.TargetPosition,
                    agvTaskid,
                    actionSort++
                );
                resultActions.Add(liftAction);
                resultActions.Add(GenerateFeedbackAction(liftAction, actionSort++));
            }
        }

        return resultActions;
    }
    // 路径点连续性验证示例
    private bool IsValidPathTransition(string from, string to)
    {
        // 示例：检查坐标格式是否一致（如 "x,y" 格式）
        if (!from.Contains(',') || !to.Contains(','))
            return false;

        var fromParts = from.Split(',');
        var toParts = to.Split(',');

        if (fromParts.Length != 2 || toParts.Length != 2)
            return false;

        // 检查是否为相邻点（简化示例，根据实际业务调整）
        int fromX = int.Parse(fromParts[0]);
        int fromY = int.Parse(fromParts[1]);
        int toX = int.Parse(toParts[0]);
        int toY = int.Parse(toParts[1]);

        // 相邻点判定：x相同且y相差1，或y相同且x相差1
        return (fromX == toX && Math.Abs(fromY - toY) == 1) ||
               (fromY == toY && Math.Abs(fromX - toX) == 1);
    }
    #endregion

    #region 动作生成方法
    private AgvactionsEntity GenerateDispatchEnterStorageAction(
        DispatchRequest request,
        ActionTypeEnum actionGroupType,
        string startPos,
        int agvTaskid,
        int actionSort)
    {
        string storagePos = actionGroupType == ActionTypeEnum.InLocation
            ? request.DispatchPosCoord
            : request.StoragePosCoord;

        return new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement,
            StartPosition = startPos,
            TargetPosition = storagePos,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = actionGroupType,
            Istype = request.Agvtype,
            GroupStartPosition = startPos,
            GroupTargetPosition = storagePos,
            Palletcode = request.Palletcode,
            AgvTaskid = agvTaskid,
            Routepoint = JsonConvert.SerializeObject(new[] { startPos, storagePos }),
            Actionsort = actionSort,
            TargetFloor = request.TargetFloor
        };
    }

    private AgvactionsEntity GenerateDispatchLiftingAction(
        DispatchRequest request,
        string position,
        int agvTaskid,
        int actionSort)
    {
        return new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement, // 或根据实际业务调整为Lifting
            StartPosition = position,
            TargetPosition = position,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = ActionTypeEnum.Lifting,
            Istype = request.Agvtype,
            GroupStartPosition = position,
            GroupTargetPosition = position,
            Palletcode = request.Palletcode,
            AgvTaskid = agvTaskid,
            Routepoint = position,
            Actionsort = actionSort,
            TargetFloor = request.TargetFloor
        };
    }

    private AgvactionsEntity GenerateDispatchUnloadingAction(
        DispatchRequest request,
        string position,
        int agvTaskid,
        int actionSort)
    {
        return new AgvactionsEntity
        {
            TaskId = request.TaskId,
            DeviceId = request.AgvCode,
            ActionType = AgvActionType.Movement, // 或根据实际业务调整为Unloading
            StartPosition = position,
            TargetPosition = position,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = ActionTypeEnum.Unloading,
            Istype = request.Agvtype,
            GroupStartPosition = position,
            GroupTargetPosition = position,
            Palletcode = request.Palletcode,
            AgvTaskid = agvTaskid,
            Routepoint = position,
            Actionsort = actionSort,
            TargetFloor = request.TargetFloor
        };
    }
    #endregion

    #region 反馈动作生成
    private AgvactionsEntity GenerateFeedbackAction(AgvactionsEntity sourceAction, int actionSort)
    {
        return new AgvactionsEntity
        {
            TaskId = sourceAction.TaskId,
            DeviceId = sourceAction.DeviceId,
            ActionType = AgvActionType.Feedback,
            StartPosition = sourceAction.TargetPosition,
            TargetPosition = sourceAction.TargetPosition,
            Status = ActionStatusEnum.Pending,
            ActionGroupType = sourceAction.ActionGroupType,
            Istype = sourceAction.Istype,
            GroupStartPosition = sourceAction.GroupStartPosition,
            GroupTargetPosition = sourceAction.GroupTargetPosition,
            Palletcode = sourceAction.Palletcode,
            AgvTaskid = sourceAction.AgvTaskid,
            Routepoint = sourceAction.TargetPosition,
            Actionsort = actionSort,
            TargetFloor = sourceAction.TargetFloor
        };
    }
    #endregion
    #region 请求验证
    private void ValidateDispatchRequest(DispatchRequest request)
    {
        if (request == null)
            throw new ArgumentNullException(nameof(request), "调度请求不能为空");

        // 基础信息验证
        if (string.IsNullOrWhiteSpace(request.TaskId))
            throw new ArgumentException("任务ID不能为空", nameof(request.TaskId));

        if (string.IsNullOrWhiteSpace(request.AgvCode))
            throw new ArgumentException("AGV设备ID不能为空", nameof(request.AgvCode));

        if (string.IsNullOrWhiteSpace(request.Agvtype))
            throw new ArgumentException("AGV类型不能为空", nameof(request.Agvtype));

        // 坐标验证
        if (string.IsNullOrWhiteSpace(request.AgvCurrentPos))
            throw new ArgumentException("AGV当前位置不能为空", nameof(request.AgvCurrentPos));

        if (string.IsNullOrWhiteSpace(request.DispatchCoord))
            throw new ArgumentException("调货货物点位不能为空", nameof(request.DispatchCoord));

        if (string.IsNullOrWhiteSpace(request.TargetPointCoord))
            throw new ArgumentException("目标货物点位不能为空", nameof(request.TargetPointCoord));

        // 库位验证
        if (string.IsNullOrWhiteSpace(request.DispatchPosCoord))
            throw new ArgumentException("调货库位坐标不能为空", nameof(request.DispatchPosCoord));

        if (string.IsNullOrWhiteSpace(request.StoragePosCoord))
            throw new ArgumentException("存储库位坐标不能为空", nameof(request.StoragePosCoord));

        // 托盘码验证（如果业务要求必须有）
        if (string.IsNullOrWhiteSpace(request.Palletcode))
            throw new ArgumentException("托盘码不能为空", nameof(request.Palletcode));

    }
    #endregion

}